#pragma once

namespace my
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr)
			:_ptr(ptr)
			,_pcount(new int(1))
		{ }

		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			,_pcount(sp._pcount)
		{
			++(*_pcount);
		}

		void release()
		{
			if (_ptr == nullptr)
				return;

			if (--(*_pcount) == 0)
			{
				delete _ptr;
				delete _pcount;

				_pcount = nullptr;
				_ptr = nullptr;
			}
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (this == &sp)
				return *this;

			release();
			_ptr = sp._ptr;
			_pcount = sp._pcount;
			++(*_pcount);

			return *this;
		}

		~shared_ptr()
		{
			release();
		}

		int get_count() const
		{
			return *_pcount;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
		int* _pcount;
	};

	template<class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{
		}

		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get())
		{
		}

		weak_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();

			return *this;
		}

	private:
		T* _ptr = nullptr;

		//T* _pcount
	};
}